// sm4.c
#include <openssl/evp.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

int sm4_encrypt(const unsigned char *plaintext, int plen,
                const unsigned char *key,
                unsigned char *ciphertext) {
    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    if (!ctx) return -1;

    if (EVP_EncryptInit_ex(ctx, EVP_sm4_ecb(), NULL, key, NULL) != 1) goto err;
    EVP_CIPHER_CTX_set_padding(ctx, 0); // 无填充

    int len;
    if (EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plen) != 1) goto err;
    int clen = len;
    if (EVP_EncryptFinal_ex(ctx, ciphertext + len, &len) != 1) goto err;
    clen += len;

    EVP_CIPHER_CTX_free(ctx);
    return clen;

err:
    EVP_CIPHER_CTX_free(ctx);
    return -1;
}

int sm4_decrypt(const unsigned char *ciphertext, int clen,
                const unsigned char *key,
                unsigned char *plaintext) {
    EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
    if (!ctx) return -1;

    if (EVP_DecryptInit_ex(ctx, EVP_sm4_ecb(), NULL, key, NULL) != 1) goto err;
    EVP_CIPHER_CTX_set_padding(ctx, 0);

    int len;
    if (EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, clen) != 1) goto err;
    int plen = len;
    if (EVP_DecryptFinal_ex(ctx, plaintext + len, &len) != 1) goto err;
    plen += len;

    EVP_CIPHER_CTX_free(ctx);
    return plen;

err:  // 修复：添加了缺失的 err 标签
    EVP_CIPHER_CTX_free(ctx);
    return -1;
}

// 辅助函数：打印十六进制
void print_hex(const char* label, const unsigned char* data, int len) {
    printf("%s: ", label);
    for (int i = 0; i < len; i++) {
        printf("%02x", data[i]);
    }
    printf("\n");
}

int main() {
    // 明文（必须是 16 字节的整数倍，因为 ECB 无填充）
    unsigned char plaintext[16] = "20231318fushuli"; // 16 字节
    int plen = 16;

    // 密钥（SM4 密钥必须为 16 字节）
    unsigned char key[16] = "0123456789abcdef";

    unsigned char ciphertext[32]; // 足够大
    unsigned char decrypted[32];

    // 加密
    int clen = sm4_encrypt(plaintext, plen, key, ciphertext);
    if (clen <= 0) {
        fprintf(stderr, "Encryption failed!\n");
        return 1;
    }

    // 解密
    int dlen = sm4_decrypt(ciphertext, clen, key, decrypted);
    if (dlen <= 0) {
        fprintf(stderr, "Decryption failed!\n");
        return 1;
    }

    // 输出结果
    print_hex("Plaintext ", plaintext, plen);
    print_hex("Key       ", key, 16);
    print_hex("Ciphertext", ciphertext, clen);
    print_hex("Decrypted ", decrypted, dlen);

    // 验证是否一致
    if (memcmp(plaintext, decrypted, plen) == 0) {
        printf("SM4 ECB 加解密成功！\n");
    } else {
        printf("加解密失败！\n");
    }

    return 0;
}




